package org.xiezc.servlet;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.xiezc.annotation.XAutowired;

/**
 * 在构造方法中加上 根据注解从spring中获得对象赋予注解的字段
 *
 * @author xiezc
 */
public class XHttpServlet extends HttpServlet {
    // 获得spring的容器
    private static ApplicationContext applicationContext;

    /**
     * 根据注解从spring中取得值赋予@XAutowired注解的字段
     */
    @Override
    public void init() throws ServletException {
        super.init();
        // 获得所有的属性
        Field[] fields = this.getClass().getDeclaredFields();

        // 遍历属性
        for (Field field : fields) {
            // 判断属性中是否有XAutowired注解
            if (field.isAnnotationPresent(XAutowired.class)) {
                try {
                    if (XHttpServlet.applicationContext == null) {
                        XHttpServlet.applicationContext = WebApplicationContextUtils
                                .getWebApplicationContext(getServletContext());
                    }
                    // 获得注解对象
                    XAutowired XAutowired = field.getAnnotation(XAutowired.class);
                    // 获得注解值
                    String className = XAutowired.value();
                    // 获得属性的名称（名称不是类型）
                    String fieldName = field.getName();
                    // 将首字母大写
                    char[] cs = fieldName.toCharArray();
                    cs[0] = Character.toUpperCase(cs[0]);
                    // 获得属性的set方法名
                    String fieldSetMethodName = "set" + String.valueOf(cs);
                    // 获得该字段的类型
                    Class<?> clazz = field.getType();
                    // 根据set方法名和参数类型获得方法
                    Method method = this.getClass().getMethod(fieldSetMethodName, clazz);
                    // 注解值为空
                    if ("".equals(className)) {
                        // 获得首字母小写的字段名称
                        cs[0] = Character.toLowerCase(cs[0]);
                        fieldName = String.valueOf(cs);
                        // 调用方法，参数是从spring中获得的
                        Object fieldObj = XHttpServlet.applicationContext.getBean(fieldName);
                        method.invoke(this, clazz.cast(fieldObj));
                    } else {// 注解值就是spring容器中的键值
                        Object fieldObj = XHttpServlet.applicationContext.getBean(className);
                        method.invoke(this, clazz.cast(fieldObj));
                    }
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}
